package com.fcscs.cservice.dao.hibernate;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.fcscs.core.dao.ConnectionManager;
import com.fcscs.core.domain.BaseEntity.DBLoc;
import com.fcscs.cservice.common.CServiceCommonEnums.RestaurantConfigType;
import com.fcscs.cservice.dao.RestaurantDao;
import com.fcscs.cservice.domain.ActivityLogs;
import com.fcscs.cservice.domain.PropertyConfigRestaurant;
import com.fcscs.cservice.domain.Restaurant;
import com.fcscs.cservice.domain.RestaurantConfig;
import com.fcscs.cservice.domain.model.RestaurantConfigModel;
import com.fcscs.cservice.domain.model.RestaurantConfiguration;
import com.fcscs.cservice.domain.model.RestaurantView;

@SuppressWarnings("unchecked")
@Repository("restaurantDao")
public class RestaurantDaoHibernate extends BaseDaoHibernate<Restaurant> implements RestaurantDao {

	private static DBLoc DBLoc = new Restaurant().getDBLoc();

	@Autowired
	private ConnectionManager connMgr;

	private static final String FIND_RESTAURANT_VIEW="select r.note as note,r.description as description,"+
	"r.business_location as bussinessLocation,r.cuisine_type_id as cuisineTypeId," +
	//	"r.business_location as bussinessLocation,r.cuisine_type_id as cuisineTypeId,r.currency as currency," +
	"r.default_respic_id as photoId,r.name as name,r.id as restaurantId,r.average_spending as averageSpending,r.smoking as smoking," +
	"t.name as cuisineType from fcs_guest.restaurant r join fcs_guest.cuisine_type t on r.cuisine_type_id=t.id " +
	"where r.org_id =:orgId and r.property_id=:propId and r.active = true and t.active=true";

	private static final String FIND_REST = "FROM Restaurant r WHERE r.orgId = :orgId AND r.propertyId = :propId AND r.active = true";
	private static final String FIND_PROP_CON_REST = "FROM PropertyConfigRestaurant p WHERE p.orgId=:orgId AND p.propertyId = :propId AND p.active = true" ;
	private static final String FIND_REST_CONFIG = "FROM RestaurantConfig rc WHERE rc.orgId=:orgId AND rc.propertyId=:propId AND rc.restaurantId=:resId AND rc.active = true";


	@Override
	protected Class<Restaurant> getCls() {
		return Restaurant.class;
	}

	@Override
	protected ConnectionManager getConnectionManager() {
		return connMgr;
	}

	@Override
	protected DBLoc getDBLoc() {
		return DBLoc;
	}

	@Override
	public <E extends Restaurant> E get(Class<E> cls, long id) {
		return (E) getConnectionManager().getCurrentSession(getDBLoc()).load(cls, id);
	}

	@Override
	public List<Restaurant> getRestaurants(long orgId, Long propId) {

		Query q = connMgr.getCurrentSession(getDBLoc()).createQuery(FIND_REST);
		q.setLong("orgId", orgId);
		q.setParameter("propId", propId, Hibernate.LONG);

		return q.list();
	}

	@Override
	public List<RestaurantView> getRestaurantViews(long orgId,Long propId){

		SQLQuery sqlQu =  connMgr.getCurrentSession(getDBLoc()).createSQLQuery(FIND_RESTAURANT_VIEW);
		sqlQu.setLong("orgId", orgId);
		sqlQu.setParameter("propId", propId, Hibernate.LONG);
		sqlQu.addScalar("note", Hibernate.STRING).
		addScalar("description", Hibernate.STRING).
		addScalar("bussinessLocation", Hibernate.STRING).
		addScalar("cuisineTypeId", Hibernate.LONG).
		//		addScalar("currency", Hibernate.STRING).
		addScalar("photoId", Hibernate.LONG).
		addScalar("name", Hibernate.STRING).
		addScalar("restaurantId", Hibernate.LONG).
		addScalar("averageSpending", Hibernate.BIG_DECIMAL).
		addScalar("smoking",Hibernate.BOOLEAN).
		addScalar("cuisineType", Hibernate.STRING);

		return sqlQu.setResultTransformer(Transformers.aliasToBean(RestaurantView.class)).list();
	}

	@Override
	public <E extends Restaurant> E save(E loc) {
		return (E) getConnectionManager().getCurrentSession(DBLoc).save(loc);
	}

	@Override
	public RestaurantConfigModel saveRestaurantConfigModel(RestaurantConfigModel model) {
		if (model == null) {
			return model;
		}
		Session session = getConnectionManager().getCurrentSession(DBLoc);
		//save property config Restaurant
		PropertyConfigRestaurant propConfigRest = model.getPropertyConRestaurant();
		session.merge(propConfigRest);
		List<RestaurantConfiguration> restConfigList = model.getRestMsgList();
		for(RestaurantConfiguration rc : restConfigList){
			//update restaurant
			Restaurant restaurant = rc.getRestaurant();
			session.merge(restaurant);
			List<RestaurantConfig> restaurantConfigList = rc.getRestConfigDetail();
			for(RestaurantConfig rcf : restaurantConfigList ){
				//update restaurantConfig
				session.merge(rcf);
			}
		}
		return model;
	}


	@Override
	public RestaurantConfigModel getRestaurantConfigModel(long orgId,Long propId) {

		RestaurantConfigModel model = new RestaurantConfigModel();
		Session session = getConnectionManager().getCurrentSession(DBLoc);
		//get property config restaurant
		Query qu = session.createQuery(FIND_PROP_CON_REST);
		qu.setLong("orgId", orgId);
		qu.setLong("propId", propId);
		if(qu.list().size() != 0 ){
			model.setPropertyConRestaurant((PropertyConfigRestaurant)(qu.list().get(0)));
		}else{
			PropertyConfigRestaurant proCoRes = new PropertyConfigRestaurant();
			proCoRes.setOrgId(orgId);
			proCoRes.setPropertyId(propId);
			session.save(proCoRes);
			model.setPropertyConRestaurant(proCoRes);
		}
		List<RestaurantConfiguration> restaurantConfig = new ArrayList<RestaurantConfiguration>();
		qu = session.createQuery(FIND_REST);
		qu.setLong("orgId", orgId);
		qu.setLong("propId", propId);
		List<Restaurant> resList = qu.list();
		//		System.out.println(resList.size()+"********************************resListSize*****************************");
		for(Restaurant r : resList){
			RestaurantConfiguration rcf = new RestaurantConfiguration();
			qu = session.createQuery(FIND_REST_CONFIG);
			qu.setLong("orgId", orgId);
			qu.setLong("propId", propId);
			qu.setLong("resId", r.getId());
			rcf.setRestaurant(r);
			if(qu.list().size() != 0){
				rcf.setRestConfigDetail((List<RestaurantConfig>)(qu.list()));
			}else{
				RestaurantConfig rcfff = new RestaurantConfig();
				rcfff.setOrgId(orgId);
				rcfff.setPropertyId(propId);
				rcfff.setRestaurantId(r.getId());
				//				//first default printer
				rcfff.setConfigTypeEnum(RestaurantConfigType.PRINTER);
				session.save(rcfff);
				List<RestaurantConfig> ll = new ArrayList<RestaurantConfig>();
				ll.add(rcfff);
				rcf.setRestConfigDetail(ll);
			}
			restaurantConfig.add(rcf);
		}
		model.setRestMsgList(restaurantConfig);

		return model;
	}

	@Override
	public RestaurantConfig saveRestaurantConfig(RestaurantConfig restConfig) {
		connMgr.getCurrentSession(DBLoc).saveOrUpdate(restConfig);
		return restConfig;
	}

	@Override
	public RestaurantConfiguration saveRestaurantConfig(RestaurantConfiguration resc) {
		
		Session session = getConnectionManager().getCurrentSession(DBLoc);
		
		Restaurant rest = resc.getRestaurant();
		session.merge(rest);
		if(resc.getRestConfigDetail().size() != 0){
			//TODO: save one
			RestaurantConfig rcf = resc.getRestConfigDetail().get(0);
			session.merge(rcf);
		}
		
		return resc;
	}
	
	@Override
	public RestaurantConfig getRestaurantConfig(long restConfigId) {
		return (RestaurantConfig) connMgr.getCurrentSession(DBLoc).get(RestaurantConfig.class, restConfigId);
	}
	
	@Override
	public List<RestaurantConfig> getRestaurantConfig(long orgId,Long propId,long restaId){
		
		String sql = "FROM RestaurantConfig rc Where rc.orgId=:orgId and rc.propertyId=:propId and rc.restaurantId=:restId and rc.active=true";
		Query q = connMgr.getCurrentSession(getDBLoc()).createQuery(sql);
		q.setLong("orgId", orgId);
		q.setParameter("propId", propId, Hibernate.LONG);
		q.setLong("restId", restaId);
		
		return q.list();
	}

	@Override
	public PropertyConfigRestaurant savePropertyConfigRestaurant(PropertyConfigRestaurant propConfigRest) {
		connMgr.getCurrentSession(DBLoc).saveOrUpdate(propConfigRest);
		return propConfigRest;
	}

	@Override
	public PropertyConfigRestaurant getPropertyConfigRestaurant(long propConfigRestId) {
		return (PropertyConfigRestaurant)connMgr.getCurrentSession(DBLoc).
		get(PropertyConfigRestaurant.class, propConfigRestId);
	}

	@Override
	public PropertyConfigRestaurant getPropertyConfigRestaurant(long orgId,Long propId) {

		String sql = "FROM PropertyConfigRestaurant pc where pc.orgId=:orgId and pc.propertyId=:propId and pc.active=true ";
		Query q = connMgr.getCurrentSession(getDBLoc()).createQuery(sql);
		q.setLong("orgId", orgId);
		q.setParameter("propId", propId, Hibernate.LONG);
		
		return (PropertyConfigRestaurant) q.uniqueResult();
	}
	
	@Override
	public List<ActivityLogs> simpFindActivityLogs(long orgId,Long propId, Long userId,Date startDate, Date endDate, int start, int resultCnt) {
		StringBuffer sql = new StringBuffer(); 
		sql.append("From ActivityLogs al where al.orgId=:orgId and al.propertyId=:propId and al.isActive=true ");
		if(userId != null){
			sql.append("and al.createBy=:userId ");
		}
		if(startDate != null){
			sql.append("and al.created >=:startDate ");
		}
		if(endDate != null){
			sql.append("and al.created <=:endDate");
		}

		Query q = connMgr.getCurrentSession(getDBLoc()).createQuery(sql.toString());
		q.setLong("orgId", orgId);
		q.setParameter("propId", propId, Hibernate.LONG);
		if(userId != null){
			q.setLong("userId", userId);
		}
		if(startDate != null){
			q.setDate("startDate", startDate);
		}
		if(endDate != null){
			q.setDate("ednDate", startDate);
		}
		q.setFirstResult(start);
		if(resultCnt >0 && resultCnt <=15){
			q.setMaxResults(resultCnt);
		}else{
			q.setMaxResults(15);
		}

		return q.list();
	}

	@Override
	public int simpFindActivityLogsCnt(long orgId, Long propId, Long userId,Date startDate, Date endDate) {
		StringBuffer sql = new StringBuffer(); 
		sql.append("From ActivityLogs al where al.orgId=:orgId and al.propertyId=:propId and al.isActive=true ");
		if(userId != null){
			sql.append("and al.createBy=:userId ");
		}
		if(startDate != null){
			sql.append("and al.created >=:startDate ");
		}
		if(endDate != null){
			sql.append("and al.created <=:endDate");
		}
		Query q = connMgr.getCurrentSession(getDBLoc()).createQuery(sql.toString());
		q.setLong("orgId", orgId);
		q.setParameter("propId", propId, Hibernate.LONG);
		if(userId != null){
			q.setLong("userId", userId);
		}
		if(startDate != null){
			q.setDate("startDate", startDate);
		}
		if(endDate != null){
			q.setDate("ednDate", startDate);
		}

		return ((Number) q.uniqueResult()).intValue();
	}

	@Override
	public List<ActivityLogs> advaFindActivityLogs(long orgId,Long propId,String actionName, String entityName,
			Long userId,String detail,Date startDate, Date endDate, int start, int resultCnt) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int advaFindActivityLogsCnt(long orgId, Long propId,String actionName, String entityName, Long userId,
			String detail, Date startDate, Date endDate) {
		// TODO Auto-generated method stub
		return 0;
	}

}
